﻿using System;
using System.Collections.Generic;
using System.Xml;
using SSP.Api.Interfaces;

namespace SSP.Api
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class DirectorUser : DirectorWrapper, IDeserializer
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DirectorUser"/> class.
        /// </summary>
        /// <param name="parent">The parent.</param>
        public DirectorUser(Director parent) : base(parent)
        {
        }

        /// <summary>
        /// The user's unique ID in the database.
        /// </summary>
        /// <value>The id.</value>
        public int Id { get; set; }

        /// <summary>
        /// Gets or sets the username.
        /// </summary>
        /// <value>The username.</value>
        public string UserName { get; set; }

        /// <summary>
        /// The user's first name.
        /// </summary>
        /// <value>The first.</value>
        public string First { get; set; }

        /// <summary>
        /// The user's last name.
        /// </summary>
        /// <value>The last.</value>
        public string Last { get; set; }

        /// <summary>
        /// The user's display name, as entered in Director.
        /// </summary>
        /// <value>The display_name.</value>
        public string DisplayName { get; set; }

        /// <summary>
        /// The user's biographical profile.
        /// </summary>
        /// <value>The profile.</value>
        public string Profile { get; set; }

        /// <summary>
        /// Array of external links, each with a name and a URL.
        /// </summary>
        /// <value>The externals.</value>
        public External[] Externals { get; set; }

        /// <summary>
        /// How many pieces of content the user has uploaded.
        /// </summary>
        /// <value>The content_count.</value>
        public int ContentCount { get; set; }

        /// <summary>
        /// The user's profile photo, returned with the parameters given to the Format class' "user" method.
        /// </summary>
        /// <value>The photos.</value>
        public Dictionary<String, DirectorImage> Photos { get; set; }

        #region IDeserializer Members

        /// <summary>
        /// Gets or sets the <see cref="System.String"/> with the specified property name.
        /// </summary>
        /// <value></value>
        public string this[string propertyName]
        {
            get { return _sDict[propertyName]; }
            set { _sDict[propertyName] = value; }
        }

        private readonly Dictionary<string, string> _sDict = new Dictionary<string, string>();

        /// <summary>
        /// Deserializes from an XmlReader and sets the object's properties.
        /// </summary>
        /// <param name="reader">The reader.</param>
        public void DeserializeFromReader(XmlReader reader)
        {
            // Start to use the reader.
            reader.Read();

            // Read all elements
            while (reader.NodeType != XmlNodeType.EndElement)
            {
                switch (reader.Name)
                {
                    case "id":
                        Id = convertToInt(reader.ReadElementContentAsString());
                        break;
                    case "username":
                        UserName = reader.ReadElementContentAsString();
                        break;
                    case "first":
                        First = reader.ReadElementContentAsString();
                        break;
                    case "last":
                        Last = reader.ReadElementContentAsString();
                        break;
                    case "display_name":
                        DisplayName = reader.ReadElementContentAsString();
                        break;
                    case "profile":
                        Profile = reader.ReadElementContentAsString();
                        break;
                    case "externals":
                        Externals = getExternals(reader);
                        break;
                    case "content_count":
                        ContentCount = reader.ReadElementContentAsInt();
                        break;
                    case "photos":
                        if (Photos == null)
                            Photos = new Dictionary<string, DirectorImage>();
                        reader.Read();

                        if (reader.NodeType == XmlNodeType.EndElement)
                        {
                            reader.ReadEndElement();
                        }
                        else
                        {
                            var eName = reader.Name;
                            var userImage = new DirectorImage(Parent);
                            userImage.DeserializeFromReader(reader);
                            Photos.Add(eName, userImage);
                        }
    
                        break;
                    default:
                        System.Diagnostics.Trace.WriteLine("Unhandled xml element name '" + reader.Name + "'.");
                        _sDict[reader.Name] = reader.ReadElementContentAsString();
                        break;
                }
                reader.MoveToContent();
            }

            // Extremely important to read the node to its end.
            // next call of the reader methods will crash if not called.
            reader.ReadEndElement();
        }

        #endregion

        /// <summary>
        /// The scope method is to be called before the all method above, and defines the scope of the users returned. It takes three parameters:
        /// </summary>
        /// <param name="scope">The scope.</param>
        public void Scope(UserScope scope)
        {
            Parent.user_scope = scope;
        }

        /// <summary>
        /// Alls the specified sort.
        /// </summary>
        /// <param name="sort">The sort.</param>
        /// <returns></returns>
        public DirectorUser[] All(string sort)
        {
            string tail = "get_users_";
            if (Parent.user_scope != null)
            {
                Parent.Post.Add("data[user_scope_model]=" + Parent.user_scope.Model);
                Parent.Post.Add("data[user_scope_id]=" + Parent.user_scope.Id);
                Parent.Post.Add("data[user_scope_all]=" + BoolToInt(Parent.user_scope.All));
                tail += Parent.user_scope.Model + "_" + Parent.user_scope.Id + "_" + BoolToInt(Parent.user_scope.All) + "_";
            }
            else
            {
                tail += "0_0_0_";
            }
            Parent.Post.Add("data[user_sort]=" + sort);
            tail += sort;
            DirectorResponse response = Parent.send("get_users", tail);
            return response.Users;
        }


        /// <summary>
        /// Alls this instance.
        /// </summary>
        /// <returns></returns>
        public DirectorUser[] All()
        {
            return All("name");
        }
    }
}